﻿using MQTTnet.Client;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using MQTTnet.Helpers;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using JESAI.MQTT.Client.Clients;
using System.Collections.Concurrent;
using JESAI.MQTT.Client.Configurations;
using JESAI.MQTT.Client.Enums;

namespace JESAI.MQTT.Client.Subscribes
{
    public class MQTTMessageSubscribe
    {
        public static async Task Subscribe(SubscribeEvent subscribeEvent)
        {
            ///*
            // * This sample subscribes to a topic and processes the received message.
            // */

            MQTTClient mqttClient = MQTTClient.Instance;
            //var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();

            //// Setup message handling before connecting so that queued messages
            //// are also handled properly. When there is no event handler attached all
            //// received messages get lost.
            //mqttClient.ApplicationMessageReceivedAsync += subscribeEvent.ApplicationMessageReceivedAsync;

            //await mqttClient.mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

            var mqttSubscribeOptions = mqttClient.mqttFactory.CreateSubscribeOptionsBuilder()
                .WithTopicFilter(
                    f =>
                    {                      
                        var builder = f.WithTopic(subscribeEvent.Topic);
                        if (subscribeEvent.mqttQualityOfServiceLevel != null)
                        {
                            builder.WithQualityOfServiceLevel(subscribeEvent.mqttQualityOfServiceLevel);
                        }

                        if (subscribeEvent.IsNoLocal)
                        {
                            builder.WithNoLocal();
                        }

                        if (subscribeEvent.IsRetainAsPublished)
                        {
                            builder.WithRetainAsPublished();
                        }

                        if (subscribeEvent.mqttRetainHandling != null)
                        {
                            builder.WithRetainHandling(subscribeEvent.mqttRetainHandling);
                        }                       
                    })
                .Build();

            await mqttClient.mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

            Console.WriteLine("MQTT client subscribed to topic.");

            Console.WriteLine("Press enter to exit.");
            Console.ReadLine();

        }
        public static async Task Subscribe(List<SubscribeEvent> subscribeEvents)
        {
            ///*
            // * This sample subscribes to a topic and processes the received message.
            // */

            MQTTClient mqttClient = MQTTClient.Instance;
            //var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com").Build();

            //// Setup message handling before connecting so that queued messages
            //// are also handled properly. When there is no event handler attached all
            //// received messages get lost.
            //mqttClient.ApplicationMessageReceivedAsync += subscribeEvent.ApplicationMessageReceivedAsync;

            //await mqttClient.mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

            var mqttSubscribeOptions = mqttClient.mqttFactory.CreateSubscribeOptionsBuilder()
                .WithTopicFilter(
                    f =>
                    {
                        foreach (var subscribeEvent in subscribeEvents)
                        {
                           var builder= f.WithTopic(subscribeEvent.Topic);
                            if (subscribeEvent.mqttQualityOfServiceLevel!=null)
                            {
                                builder.WithQualityOfServiceLevel(subscribeEvent.mqttQualityOfServiceLevel);
                            }

                            if (subscribeEvent.IsNoLocal)
                            {
                                builder.WithNoLocal();
                            }

                            if (subscribeEvent.IsRetainAsPublished)
                            {
                                builder.WithRetainAsPublished();
                            }

                            if (subscribeEvent.mqttRetainHandling!=null)
                            {
                                builder.WithRetainHandling(subscribeEvent.mqttRetainHandling);
                            }
                        }
                    })
                .Build();

            await mqttClient.mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

            Console.WriteLine("MQTT client subscribed to topic.");

            Console.WriteLine("Press enter to exit.");
            Console.ReadLine();
            
        }

        //public static async Task Send_Responses(SubscribeEvent subscribeEvent)
        //{
        //    /*
        //     * This sample subscribes to a topic and sends a response to the broker. This requires at least QoS level 1 to work!
        //     */

        //    MQTTClient mqttClient = MQTTClient.Instance;
        //    mqttClient.ApplicationMessageReceivedAsync += subscribeEvent.ApplicationMessageReceivedAsync;
        //    //delegate (MqttApplicationMessageReceivedEventArgs args)
        //    //    {
        //    //        // Do some work with the message...

        //    //        // Now respond to the broker with a reason code other than success.
        //    //        args.ReasonCode = MqttApplicationMessageReceivedReasonCode.ImplementationSpecificError;
        //    //        args.ResponseReasonString = "That did not work!";

        //    //        // User properties require MQTT v5!
        //    //        args.ResponseUserProperties.Add(new MqttUserProperty("My", "Data"));

        //    //        // Now the broker will resend the message again.
        //    //        return Task.CompletedTask;
        //    //    };


        //    var mqttSubscribeOptions = mqttClient.mqttFactory.CreateSubscribeOptionsBuilder()
        //            .WithTopicFilter(
        //                f =>
        //                {
        //                    f.WithTopic(subscribeEvent.Topic);
        //                })
        //            .Build();

        //        var response = await mqttClient.mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

        //        Console.WriteLine("MQTT client subscribed to topic.");

        //        // The response contains additional data sent by the server after subscribing.
        //        response.DumpToConsole();
            
        //}

        //public static async Task Subscribe_Multiple_Topics(List<SubscribeEvent> subscribeEvents)
        //{
        //    /*
        //     * This sample subscribes to several topics in a single request.
        //     */
        //    MQTTClient mqttClient = await GetMQTTClient(subscribeEvent.Topic);

        //    // Create the subscribe options including several topics with different options.
        //    // It is also possible to all of these topics using a dedicated call of _SubscribeAsync_ per topic.
        //    var mqttSubscribeOptions = mqttClient.mqttFactory.CreateSubscribeOptionsBuilder()
        //        .WithTopicFilter(
        //            f =>
        //            {
        //                f.WithTopic("mqttnet/samples/topic/1");
        //            })
        //        .WithTopicFilter(
        //            f =>
        //            {
        //                f.WithTopic("mqttnet/samples/topic/2").WithNoLocal();
        //            })
        //        .WithTopicFilter(
        //            f =>
        //            {
        //                f.WithTopic("mqttnet/samples/topic/3").WithRetainHandling(MqttRetainHandling.SendAtSubscribe);
        //            })
        //        .Build();

        //    var response = await mqttClient.mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

        //    Console.WriteLine("MQTT client subscribed to topics.");

        //    // The response contains additional data sent by the server after subscribing.
        //    response.DumpToConsole();
            
        //}

        //public static async Task Subscribe_Topic(SubscribeEvent subscribeEvent)
        //{
        //    /*
        //     * This sample subscribes to a topic.
        //     */
        //    MQTTClient mqttClient = await GetMQTTClient(subscribeEvent.Topic);
        //    var mqttSubscribeOptions = mqttClient.mqttFactory.CreateSubscribeOptionsBuilder()
        //        .WithTopicFilter(
        //            f =>
        //            {
        //                f.WithTopic(subscribeEvent.Topic).WithAtMostOnceQoS();
        //            })
        //        .Build();

        //    var response = await mqttClient.mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

        //    Console.WriteLine("MQTT client subscribed to topic.");

        //    // The response contains additional data sent by the server after subscribing.
        //    response.DumpToConsole();
            
        //}
    }
}
